﻿using AutoMapper;
using ProjectManageSystemApi.DbEntity;
using ProjectManageSystemApi.Enums;
using ProjectManageSystemApi.Models;
using ProjectManageSystemApi.Models.BuildingSiteBillModel;
using ProjectManageSystemApi.Utilities;
using System;
using System.Collections.Generic;

namespace ProjectManageSystemApi.Services.Impl
{
    public class BuildingSiteBillServices : ServicesBase, IBuildingSiteBillServices
    {
        readonly IBuildingSiteBillImagesServices _imagesServices;
        public BuildingSiteBillServices(IFreeSql fsql, IMapper mapper, IBuildingSiteBillImagesServices imagesServices)
            : base(fsql, mapper)
        {
            _imagesServices = imagesServices;
        }

        public bool AddBillAndImages(AddBuildingSiteBillDto dto, long userId)
        {
            try
            {
                _fsql.Transaction(() =>
                {
                    var data = _mapper.Map<BuildingSiteBill>(dto);
                    data.CreateUser = userId;
                    data.CreateTime = DateTime.Now;
                    data.Status = (byte)BuildingSiteBillStatus.Default;
                    uint id = (uint)_fsql.Insert<BuildingSiteBill>(data).ExecuteIdentity();
                    if (id <= 0)
                    {
                        throw new DbTranException("增加 building_site_bill 表失败");
                    }
                    bool r = _imagesServices.Add(id, dto.Images);
                    if (!r)
                    {
                        throw new DbTranException("增加 building_site_bill_imager 表失败");
                    }
                });
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool UpdBillAndImages(UpdBuildingSiteBillDto dto)
        {
            try
            {
                _fsql.Transaction(() =>
                {
                    var data = _mapper.Map<BuildingSiteBill>(dto);
                    var r = _fsql.Update<BuildingSiteBill>(data.Id)
                        .Set(x => x.BillNo, dto.BillNo)
                        .Set(x => x.Name, dto.Name)
                        .Set(x => x.Quantity, dto.Quantity)
                        .Set(x => x.Unit, dto.Unit)
                        .Set(x => x.UnitPrice, dto.UnitPrice)
                        .ExecuteAffrows();
                    if (r <= 0)
                    {
                        throw new DbTranException("修改 building_site_bill 表失败");
                    }

                    _imagesServices.DelAll(dto.Id);
                    if (dto.Images == null || dto.Images.Count < 0)
                    {
                        return;
                    }

                    var updResult = _imagesServices.Add(dto.Id, dto.Images);
                    if (!updResult)
                    {
                        throw new DbTranException("增加 building_site_bill_imager 表失败");
                    }
                });
                return true;
            }
            catch
            {
                return false;
            }
        }

        public PageVo<List<BuildingSiteBillDto>> Get(PageBo<BuildingSiteBillParams> pageBo)
        {
            var data = _fsql.Select<BuildingSiteBill>()
                .Include(x => x.CreateUserInfo)
                .Include(x => x.ReturnUserInfo)
                .Include(x => x.ConfirmUserInfo)
                .Include(x => x.ProjectInfo)
                .IncludeMany(x => x.Images)
                .WhereIf(pageBo.Param.StartTime.HasValue && pageBo.Param.EndTime.HasValue && pageBo.Param.StartTime.Value != default && pageBo.Param.EndTime.Value != default,
                    x => x.CreateTime >= pageBo.Param.StartTime.Value.Date 
                        && x.CreateTime < pageBo.Param.EndTime.Value.Date.AddDays(1))
                .WhereIf(pageBo.Param.ProjectId.HasValue && pageBo.Param.ProjectId.Value > 0,
                    x => x.ProjectId == pageBo.Param.ProjectId)
                .WhereIf(!string.IsNullOrWhiteSpace(pageBo.Param.Name),
                    x => x.Name.Contains(pageBo.Param.Name))
                .WhereIf(pageBo.Param.CreateUser.HasValue && pageBo.Param.CreateUser > 0,
                    x => x.CreateUser == pageBo.Param.CreateUser.Value)
                .WhereIf(pageBo.Param.Status > -1, x => x.Status == pageBo.Param.Status)
                .OrderBy(x => x.Status)
                .OrderByDescending(x => x.CreateTime)
                ;
            PageVo<List<BuildingSiteBillDto>> result = new PageVo<List<BuildingSiteBillDto>>()
            {
                Page = pageBo.Page,
                Size = pageBo.Size
            };
            result.Total = data.Count();
            var datas = data.Page(pageBo.Page, pageBo.Size).ToList();
            result.Datas = _mapper.Map<List<BuildingSiteBillDto>>(datas);
            return result;
        }

        public bool DelBill(uint id)
        {
            return _fsql.Delete<BuildingSiteBill>(id).ExecuteAffrows() > 0;
        }

        public bool ReturnBack(BuildingSiteBillReturnDto dto, long userId)
        {
            return _fsql.Update<BuildingSiteBill>(dto.Id)
                .Set(x => x.Status, (byte)BuildingSiteBillStatus.Return)
                .Set(x => x.ReturnDesc, dto.Desc)
                .Set(x => x.ReturnTime, DateTime.Now)
                .Set(x => x.ReturnUser, userId)
                .ExecuteAffrows() > 0;
        }

        /// <summary>
        /// 获取回退订单列表
        /// </summary>
        /// <returns></returns>
        public PageVo<List<BuildingSiteBillDto>> GetReturnBack(PageBo<BuildingSiteBillReturnBackParams> pageBo, long userId)
        {
            var data = _fsql.Select<BuildingSiteBill>()
                .Include(x => x.CreateUserInfo)
                .Include(x => x.ReturnUserInfo)
                .Include(x => x.ConfirmUserInfo)
                .Include(x => x.ProjectInfo)
                .IncludeMany(x => x.Images)
                .WhereIf(!string.IsNullOrWhiteSpace(pageBo.Param.Name), x => x.Name.Contains(pageBo.Param.Name))
                .Where(x => x.CreateUser == userId)
                .Where(x => x.Status == (byte)BuildingSiteBillStatus.Return)
                .OrderByDescending(x => x.CreateTime)
                ;
            PageVo<List<BuildingSiteBillDto>> result = new PageVo<List<BuildingSiteBillDto>>()
            {
                Page = pageBo.Page,
                Size = pageBo.Size
            };
            result.Total = data.Count();
            var datas = data.Page(pageBo.Page, pageBo.Size).ToList();
            result.Datas = _mapper.Map<List<BuildingSiteBillDto>>(datas);
            return result;
        }

        public bool ResetReturnBackById(ResetBuildingSiteBill data)
        {
            var d = _fsql.Update<BuildingSiteBill>(data.Id)
                .Set(x => x.Status, (byte)BuildingSiteBillStatus.Default)
                ;
            if (!string.IsNullOrWhiteSpace(data.BillDesc))
            {
                d = d.Set(x => x.BillDesc, data.BillDesc);
            }
            return d.ExecuteAffrows() > 0;
        }

        public bool ConfirmBillById(uint id, long userId)
        {
            return _fsql.Update<BuildingSiteBill>(id)
                .Set(x => x.Status, (byte)BuildingSiteBillStatus.Confirm)
                .Set(x => x.ConfirmUser, userId)
                .Set(x => x.ConfirmTime, DateTime.Now)
                .ExecuteAffrows() > 0;
        }

        public bool ExistBillNoById(string billNo, uint id = 0)
        {
            return _fsql.Select<BuildingSiteBill>()
                .WhereIf(id > 0, x => x.Id != id)
                .Any(x => x.BillNo == billNo);
        }

        public bool ExistId(uint id)
        {
            return _fsql.Select<BuildingSiteBill>().Any(x => x.Id == id);
        }
    }
}
